/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.saga.lib.asyncserver;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;

/**
 *
 * @author summers
 */
public class Server implements AutoCloseable{

    private static final Logger LOG = Logger.getLogger("Server");
    private final int port;
    private ServerThread thread = null;

    
    private final ConnectionCompletionHandler handler;
    
    /**
     * 
     * @param port port to listen to, Guice can inject it using the name "defaultPort"
     * @param handler this is the configured connection completion handler.  
     */
    @Inject
    public Server(@Named("defaultPort")Integer port, ConnectionCompletionHandler handler) {
        this.port = port;
        this.handler = handler;
    }

    public void start() {
        thread = new ServerThread(port);
        new Thread(thread).start();
    }

    public void stop() {
        thread.stop();
    }

    public void accept() {
        thread.run();
    }

    @Override
    public void close() throws Exception {
        if (thread.run) {
            stop();
        }
        this.start();
    }

    private class ServerThread implements Runnable {

        final AsynchronousServerSocketChannel incoming;
        boolean run = true;

        /**
         *
         * @param socket
         * @throws SocketException if there is a tcp connection problem.
         */
        public ServerThread(int port) {
            try {
                incoming = AsynchronousServerSocketChannel.open();
                incoming.bind(new InetSocketAddress(port));
            } catch (IOException ex) {
                LOG.log(Level.SEVERE, "Error in server thread.", ex);
                throw new IllegalStateException(ex);
            }

        }

        @Override
        public void run() {
            if (run) {
                incoming.accept(Server.this, handler);
                LOG.log(Level.INFO, "conneciton ok.");
            }
        }

        private void stop() {
            try {
                incoming.close();
            } catch (IOException ex) {
                LOG.log(Level.INFO, "incoming was bitchy.", ex);
            }
            run = false;
        }

        private void startup() {
            LOG.log(Level.INFO, "Startup complete");
        }

        private void shutdown() {
            LOG.log(Level.INFO, "Shutdown complete");
        }

    }
}
